package yang.itcode.service.impl;

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import yang.itcode.exception.BusinessException;
import yang.itcode.mapper.*;
import yang.itcode.model.pojo.*;
import yang.itcode.service.PurchaseOrderService;
import yang.itcode.utils.ThreadUtil;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.util.List;

import static yang.itcode.constant.ErrorConstant.*;
import static yang.itcode.constant.OptionConstant.*;

@Service
public class PurchaseOrderServiceImpl implements PurchaseOrderService {

    @Autowired
    private PurchaseOrderMapper purchaseOrderMapper;
    @Autowired
    private PurchaseOrderItemMapper purchaseOrderItemMapper;
    @Autowired
    private InventoryDetailMapper inventoryDetailMapper;
    @Autowired
    private SalesOrderItemMapper salesOrderItemMapper;
    @Autowired
    private CostMapper costMapper;

    @Override
    @Transactional
    public boolean createPurchaseOrder(JSONObject form) {
        Integer userId = ThreadUtil.getCurrentId();
        String orderNo = form.getStr("orderNo");
        Integer supplierId = form.getInt("supplierId");
        LocalDate orderDate = form.get("orderDate", LocalDate.class);
        String note = form.getStr("note");
        JSONArray items = form.getJSONArray("items");
        BigDecimal totalAmount = form.getBigDecimal("totalAmount");
        List<JSONObject> itemList = items.toList(JSONObject.class);
        // 参数校验
        if (orderNo == null || supplierId == null || orderDate == null || totalAmount == null) {
            throw new BusinessException(PURCHASE_ORDER_PARAM_EXCEPTION_CODE, PURCHASE_ORDER_PARAM_EXCEPTION_MESSAGE);
        }
        BigDecimal calculatedTotalAmount = BigDecimal.ZERO;
        for (JSONObject item : itemList) {
            Integer productId = item.getInt("productId");
            String code = item.getStr("code");
            String name = item.getStr("name");
            BigDecimal quantity = item.getBigDecimal("quantity");
            BigDecimal unitPrice = item.getBigDecimal("unitPrice");
            BigDecimal totalPrice = item.getBigDecimal("totalPrice");
            String priceMode = item.getStr("priceMode");
            if (productId == null || code == null || name == null || quantity == null || unitPrice == null || totalPrice == null || priceMode == null) {
                throw new BusinessException(PURCHASE_ORDER_PARAM_EXCEPTION_CODE, PURCHASE_ORDER_PARAM_EXCEPTION_MESSAGE);
            }
            calculatedTotalAmount = calculatedTotalAmount.add(totalPrice);
            if ("total".equals(priceMode)) {
                // 校验总价模式（判断总价除以数量是否等于单价，计算保留两位小数）
                BigDecimal calculatedUnitPrice = totalPrice.divide(quantity, 2, RoundingMode.HALF_UP);
                if (calculatedUnitPrice.compareTo(unitPrice) != 0) {
                    throw new BusinessException(PURCHASE_PRICE_EXCEPTION_CODE, PURCHASE_PRICE_EXCEPTION_MESSAGE);
                }
            } else if ("unit".equals(priceMode)) {
                // 校验单价模式（判断单价乘以数量是否等于总价，计算保留两位小数）
                BigDecimal calculatedTotalPrice = unitPrice.multiply(quantity).setScale(2, RoundingMode.HALF_UP);
                if (calculatedTotalPrice.compareTo(totalPrice) != 0) {
                    throw new BusinessException(PURCHASE_PRICE_EXCEPTION_CODE, PURCHASE_PRICE_EXCEPTION_MESSAGE);
                }
            } else {
                throw new BusinessException(PURCHASE_PRICE_EXCEPTION_CODE, PURCHASE_PRICE_EXCEPTION_MESSAGE);
            }
        }
        if (calculatedTotalAmount.compareTo(totalAmount) != 0) {
            throw new BusinessException(PURCHASE_PRICE_EXCEPTION_CODE, PURCHASE_PRICE_EXCEPTION_MESSAGE);
        }
        PurchaseOrder purchaseOrder = new PurchaseOrder();
        purchaseOrder.setOrderNo(orderNo);
        purchaseOrder.setSupplierId(supplierId);
        purchaseOrder.setOrderDate(orderDate);
        purchaseOrder.setNote(note);
        purchaseOrder.setTotalAmount(totalAmount);
        purchaseOrder.setCreateUserId(userId);
        purchaseOrder.setUpdateUserId(userId);
        purchaseOrderMapper.insert(purchaseOrder);
        JSONObject condition = new JSONObject();
        condition.set("orderNo", orderNo);
        List<PurchaseOrder> lastInsert = purchaseOrderMapper.selectByCondition(condition);
        if (lastInsert.isEmpty()){
            return false;
        }
        purchaseOrder = lastInsert.get(0);
        // 插入明细并同步更新库存明细
        for (JSONObject item : itemList) {
            Integer productId = item.getInt("productId");
            BigDecimal quantity = item.getBigDecimal("quantity");
            BigDecimal unitPrice = item.getBigDecimal("unitPrice");
            BigDecimal totalPrice = item.getBigDecimal("totalPrice");

            // 1) 插入采购明细
            PurchaseOrderItem purchaseOrderItem = new PurchaseOrderItem();
            purchaseOrderItem.setOrderId(purchaseOrder.getId());
            purchaseOrderItem.setProductId(productId);
            purchaseOrderItem.setQuantity(quantity);
            purchaseOrderItem.setUnitPrice(unitPrice);
            purchaseOrderItem.setTotalPrice(totalPrice);
            purchaseOrderItem.setCreateUserId(userId);
            purchaseOrderItem.setUpdateUserId(userId);
            purchaseOrderItemMapper.insert(purchaseOrderItem);

            // 2) 查询该商品最近一条库存明细
            PageHelper.startPage(1, 1);
            condition = new JSONObject();
            condition.set("productId", productId);
            condition.set("orderBy", "create_time");
            condition.set("sortOrder", "DESC");
            List<InventoryDetail> latestList = inventoryDetailMapper.selectByCondition(condition);
            InventoryDetail latest = latestList.isEmpty() ? null : latestList.get(0);
            BigDecimal prevBalanceQty = (latest != null && latest.getBalanceQuantity() != null) ? latest.getBalanceQuantity() : BigDecimal.ZERO;

            // 3) 计算本次操作后库存数量
            BigDecimal balanceQty = prevBalanceQty.add(quantity).setScale(2, RoundingMode.HALF_UP);

            // 4) 查询该商品所有历史采购记录，在业务层计算加权平均成本
            JSONObject itemCondition = new JSONObject();
            itemCondition.set("productId", productId);
            itemCondition.set("status", 1);
            List<PurchaseOrderItem> historyItems = purchaseOrderItemMapper.selectByCondition(itemCondition);

            BigDecimal totalQtySum = historyItems.stream().map(PurchaseOrderItem::getQuantity).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal totalPriceSum = historyItems.stream().map(PurchaseOrderItem::getTotalPrice).reduce(BigDecimal.ZERO, BigDecimal::add);

            BigDecimal currentAvgCost = BigDecimal.ZERO;
            if (totalQtySum.compareTo(BigDecimal.ZERO) > 0) {
                currentAvgCost = totalPriceSum.divide(totalQtySum, 2, RoundingMode.HALF_UP);
            }

            // 5) 余额价值 = 操作后库存 * 当前平均成本
            BigDecimal balanceValue = balanceQty.multiply(currentAvgCost).setScale(2, RoundingMode.HALF_UP);

            // 6) 写入库存明细（采购入库）
            InventoryDetail inventoryDetail = new InventoryDetail();
            inventoryDetail.setProductId(productId);
            inventoryDetail.setOperationType(INVENTORY_OPTION_PURCHASE);
            inventoryDetail.setQuantity(quantity);
            inventoryDetail.setUnitCost(unitPrice);
            inventoryDetail.setTotalCost(totalPrice);
            inventoryDetail.setCurrentAvgCost(currentAvgCost);
            inventoryDetail.setBalanceQuantity(balanceQty);
            inventoryDetail.setBalanceValue(balanceValue);
            inventoryDetail.setDate(orderDate);
            inventoryDetail.setNote("采购入库，采购单号：" + orderNo);
            inventoryDetail.setRelatedId(purchaseOrderItem.getId());
            inventoryDetail.setCreateUserId(userId);
            inventoryDetail.setUpdateUserId(userId);
            inventoryDetailMapper.insert(inventoryDetail);

            // 写入成本表
            Cost cost = new Cost();
            cost.setProductId(productId);
            cost.setDate(orderDate);
            cost.setOperationType(COST_OPERATION_PURCHASE);
            cost.setCurrentAvgCost(currentAvgCost);
            cost.setRelatedId(purchaseOrderItem.getId());
            cost.setNote("采购入库，采购单id：" + purchaseOrder.getId());
            cost.setCreateUserId(userId);
            cost.setUpdateUserId(userId);
            costMapper.insert(cost);
        }
        return true;
    }

    @Override
    @Transactional
    public PageInfo<JSONObject> getPurchaseOrderList(Integer pageNum, Integer pageSize, JSONObject condition) {
        PageHelper.startPage(pageNum, pageSize);
        LocalDate[] dateRange = condition.get("dateRange", LocalDate[].class);
        if (dateRange != null && dateRange.length == 2) {
            condition.set("startDate", dateRange[0]);
            condition.set("endDate", dateRange[1]);
        }
        List<JSONObject> list = purchaseOrderMapper.selectPurchaseOrderView(condition);
        checkRed : for (int i = 0; i < list.size(); i++) {
            if (list.get(i).getInt("canRed") != 1){
                list.get(i).set("canRed", false);
                continue;
            }
            list.get(i).set("canRed", true);
            condition = new JSONObject();
            condition.set("orderId", list.get(i).getInt("id"));
            condition.set("status", 1);
            // 查询所有商品
            List<PurchaseOrderItem> items = purchaseOrderItemMapper.selectByCondition(condition);
            // 遍历所有商品，判断是否有在本次采购之后有销售
            for (PurchaseOrderItem item : items) {
                condition = new JSONObject();
                condition.set("productId", item.getProductId());
                condition.set("status", 1);
                condition.set("startTime", item.getCreateTime());
                List<SalesOrderItem> laterSaleItems = salesOrderItemMapper.selectByCondition(condition);
                if (!laterSaleItems.isEmpty()) {
                    list.get(i).set("canRed", false);
                    continue checkRed;
                }
            }
        }
        return new PageInfo<>(list);
    }

    @Override
    public JSONObject getPurchaseOrderDetail(Integer id) {
        JSONObject condition = new JSONObject();
        if (id == null) {
            throw new BusinessException(PURCHASE_ORDER_PARAM_EXCEPTION_CODE, PURCHASE_ORDER_PARAM_EXCEPTION_MESSAGE);
        }
        PageHelper.startPage(1, 1);
        condition.set("id", id);
        condition.set("orderBy", "create_time");
        condition.set("sortOrder", "DESC");
        List<JSONObject> list = purchaseOrderMapper.selectPurchaseOrderView(condition);
        if (list.isEmpty()) {
            throw new BusinessException(PURCHASE_ORDER_NOT_EXIST_EXCEPTION_CODE, PURCHASE_ORDER_NOT_EXIST_EXCEPTION_MESSAGE);
        }
        JSONObject base = list.get(0);
        condition = new JSONObject();
        condition.set("orderId", id);
        List<JSONObject> items = purchaseOrderItemMapper.selectPurchaseOrderItemsView(condition);
        base.set("items", items);
        return base;
    }

    @Override
    public boolean updatePurchaseOrder(JSONObject obj) {
        Integer id = obj.getInt("id");
        String orderNo = obj.getStr("orderNo");
        Integer supplierId = obj.getInt("supplierId");
        String note = obj.getStr("note");
        if (id == null || orderNo == null || supplierId == null) {
            throw new BusinessException(PURCHASE_ORDER_PARAM_EXCEPTION_CODE, PURCHASE_ORDER_PARAM_EXCEPTION_MESSAGE);
        }
        Integer userId = ThreadUtil.getCurrentId();
        PurchaseOrder purchaseOrder = new PurchaseOrder();
        purchaseOrder.setId(id);
        purchaseOrder.setOrderNo(orderNo);
        purchaseOrder.setSupplierId(supplierId);
        purchaseOrder.setNote(note);
        purchaseOrder.setUpdateUserId(userId);
        return purchaseOrderMapper.update(purchaseOrder) == 1;
    }

    @Override
    @Transactional
    public boolean redPurchaseOrder(Integer id) {
        Integer userId = ThreadUtil.getCurrentId();
        // 查询要红冲的采购单
        JSONObject condition = new JSONObject();
        PurchaseOrder purchaseOrder = purchaseOrderMapper.selectById(id);
        if (purchaseOrder == null) {
            throw new BusinessException(PURCHASE_ORDER_NOT_EXIST_EXCEPTION_CODE, PURCHASE_ORDER_NOT_EXIST_EXCEPTION_MESSAGE);
        }
        // 查询该采购单所有商品
        condition.set("orderId", id);
        condition.set("status", 1);
        List<PurchaseOrderItem> items = purchaseOrderItemMapper.selectByCondition(condition);
        // 创建红冲采购单
        PurchaseOrder redOrder = new PurchaseOrder();
        redOrder.setOrderNo(purchaseOrder.getOrderNo() + "-R");
        redOrder.setSupplierId(purchaseOrder.getSupplierId());
        redOrder.setTotalAmount(purchaseOrder.getTotalAmount().negate());
        redOrder.setOrderDate(LocalDate.now());
        redOrder.setNote("红冲单，原采购单ID：" + id);
        redOrder.setRedOrder(1);
        redOrder.setRedSourceId(purchaseOrder.getId());
        redOrder.setCreateUserId(userId);
        redOrder.setUpdateUserId(userId);
        purchaseOrderMapper.insert(redOrder);
        // 查询刚插入的红冲单
        condition = new JSONObject();
        condition.set("orderNo", redOrder.getOrderNo());
        condition.set("status", 1);
        condition.set("orderBy", "create_time");
        condition.set("sortOrder", "DESC");
        PageHelper.startPage(1, 1);
        List<PurchaseOrder> lastInsert = purchaseOrderMapper.selectByCondition(condition);
        if (lastInsert.isEmpty()) {
            throw new BusinessException(PURCHASE_ORDER_RED_EXCEPTION_CODE, PURCHASE_ORDER_RED_EXCEPTION_MESSAGE);
        }
        redOrder = lastInsert.get(0);
        // 更新原采购单状态为已红冲
        purchaseOrder.setRedSource(1);
        purchaseOrder.setRedOrderId(redOrder.getId());
        purchaseOrder.setUpdateUserId(userId);
        purchaseOrderMapper.update(purchaseOrder);
        // 遍历商品，插入红冲采购单明细，并更新库存，更新成本
        for (PurchaseOrderItem item : items) {
            // 1) 插入红冲采购单明细
            PurchaseOrderItem redItem = new PurchaseOrderItem();
            redItem.setOrderId(redOrder.getId());
            redItem.setProductId(item.getProductId());
            redItem.setQuantity(item.getQuantity().negate());
            redItem.setUnitPrice(item.getUnitPrice());
            redItem.setTotalPrice(item.getTotalPrice().negate());
            redItem.setCreateUserId(userId);
            redItem.setUpdateUserId(userId);
            purchaseOrderItemMapper.insert(redItem);
            // 查询该商品最近一条库存明细
            condition = new JSONObject();
            condition.set("productId", item.getProductId());
            condition.set("orderBy", "create_time");
            condition.set("sortOrder", "DESC");
            PageHelper.startPage(1, 1);
            List<InventoryDetail> latestList = inventoryDetailMapper.selectByCondition(condition);
            InventoryDetail latest = latestList.isEmpty() ? null : latestList.get(0);
            BigDecimal prevBalanceQty = (latest != null && latest.getBalanceQuantity() != null) ? latest.getBalanceQuantity() : BigDecimal.ZERO;
            // 2) 插入库存明细
            InventoryDetail inventoryDetail = new InventoryDetail();
            inventoryDetail.setProductId(item.getProductId());
            inventoryDetail.setOperationType(INVENTORY_OPTION_RED_PURCHASE);
            inventoryDetail.setQuantity(item.getQuantity().negate());
            inventoryDetail.setUnitCost(item.getUnitPrice());
            inventoryDetail.setTotalCost(item.getTotalPrice().negate());
            // 计算红冲后单价、库存、总价值
            BigDecimal balanceQty = prevBalanceQty.subtract(inventoryDetail.getQuantity().negate()).setScale(2, RoundingMode.HALF_UP);
            BigDecimal balanceValue = latest.getBalanceValue().add(inventoryDetail.getTotalCost()).setScale(2, RoundingMode.HALF_UP);
            BigDecimal currentAvgCost = BigDecimal.ZERO;
            if (balanceQty.compareTo(BigDecimal.ZERO) > 0) {
                currentAvgCost = balanceValue.divide(balanceQty, 2, RoundingMode.HALF_UP);
            }
            inventoryDetail.setBalanceQuantity(balanceQty);
            inventoryDetail.setBalanceValue(balanceValue);
            inventoryDetail.setCurrentAvgCost(currentAvgCost);
            inventoryDetail.setDate(LocalDate.now());
            inventoryDetail.setNote("采购单红冲，原采购单ID：" + id + "，红冲单ID：" + redOrder.getId());
            inventoryDetail.setRelatedId(redItem.getId());
            inventoryDetail.setCreateUserId(userId);
            inventoryDetail.setUpdateUserId(userId);
            inventoryDetailMapper.insert(inventoryDetail);
            // 3) 写入成本表
            Cost cost = new Cost();
            cost.setProductId(item.getProductId());
            cost.setDate(LocalDate.now());
            cost.setOperationType(COST_OPERATION_RED_PURCHASE);
            cost.setCurrentAvgCost(currentAvgCost);
            cost.setRelatedId(redItem.getId());
            cost.setNote("采购单红冲，原采购单ID：" + id + "，红冲单ID：" + redOrder.getId());
            cost.setCreateUserId(userId);
            cost.setUpdateUserId(userId);
            costMapper.insert(cost);
        }
        return true;
    }
}
